#include "threadpool.h"
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <iostream>
using namespace std;

template <typename T>
ThreadPool<T>::ThreadPool(int min, int max)
{
    do
    {
        taskQ = new TaskQueue<T>;
        if (taskQ == nullptr)
        {
            cout << "new taskQ fail " << endl;
            break;
        }
        threadIDs = new pthread_t[max];
        if (threadIDs == nullptr)
        {
            cout << "new threadIDs fail " << endl;
            break;
        }
        memset(threadIDs, 0, sizeof(pthread_t) * max);
        minNum = min;
        maxNum = max;
        busyNum = 0;
        liveNum = min;
        exitNum = 0;
        if (pthread_mutex_init(&mutexPool, NULL) != 0 ||
            pthread_cond_init(&notEmpty, NULL) != 0)
        {
            cout << "mutex or condition init fail " << endl;
            break;
        }
        shutdown = false;
        // 管理线程和工作线程创建
        pthread_create(&managerID, NULL, manager, this);
        for (int i = 0; i < min; i++)
        {
            pthread_create(&threadIDs[i], NULL, worker, this);
        }
        return;
    } while (0);
    // 释放资源
    if (threadIDs)
    {
        delete[] threadIDs;
    }
    if (taskQ)
    {
        delete taskQ;
    }
}

template <typename T>
void *ThreadPool<T>::worker(void *arg)
{
    ThreadPool *pool = static_cast<ThreadPool *>(arg);
    while (1)
    {
        pthread_mutex_lock(&pool->mutexPool);
        // 当前队列是否为空
        while (pool->taskQ->taskNumber() == 0 && !pool->shutdown)
        {
            // 阻塞工作线程
            pthread_cond_wait(&pool->notEmpty, &pool->mutexPool);
            // 判断是否销毁线程
            if (pool->exitNum > 0)
            {
                pool->exitNum--;
                if (pool->liveNum > pool->minNum)
                {
                    pool->liveNum--;
                    pthread_mutex_unlock(&pool->mutexPool);
                    pool->threadExit();
                }
            }
        }
        // 判断线程池是否关闭
        if (pool->shutdown)
        {
            pthread_mutex_unlock(&pool->mutexPool);
            pool->threadExit();
        }
        // 从任务队列取任务
        Task task = pool->taskQ->takeTask();
        pool->busyNum++;
        // 解锁
        pthread_mutex_unlock(&pool->mutexPool);
        // 工作
        pthread_t pid = pthread_self();
        cout << "thread " << to_string(pid) << " start working \n"
             << endl;
        task.function(task.arg);
        free(task.arg);
        task.arg = nullptr;
        cout << "thread " << to_string(pid) << " end working \n"
             << endl;
        pthread_mutex_lock(&pool->mutexPool);
        pool->busyNum--;
        pthread_mutex_unlock(&pool->mutexPool);
    }
}

template <typename T>
void *ThreadPool<T>::manager(void *arg)
{
    ThreadPool *pool = static_cast<ThreadPool *>(arg);
    while (!pool->shutdown)
    {
        // 每隔3秒访问一次
        sleep(3);
        // 取出线程池中任务的数量,当前线程,工作线程的数量
        pthread_mutex_lock(&pool->mutexPool);
        int queueSize = pool->taskQ->taskNumber();
        pthread_mutex_unlock(&pool->mutexPool);
        int liveNum = pool->getAliveNum();
        int busyNum = pool->getBusyNum();
        // 添加线程
        // 任务个数>存活线程个数 && 存活线程数 < 最大线程数
        if (queueSize > liveNum && liveNum < pool->maxNum)
        {
            pthread_mutex_lock(&pool->mutexPool);
            int counter = 0;
            for (int i = 0; i < pool->maxNum && counter < NUMBER && pool->liveNum < pool->maxNum; i++)
            {
                if (pool->threadIDs[i] == 0)
                {
                    pthread_create(&pool->threadIDs[i], NULL, worker, pool);
                    counter++;
                    pool->liveNum++;
                }
            }
            pthread_mutex_unlock(&pool->mutexPool);
        }
        // 销毁线程
        // 忙线程*2 < 存活线程数 && 存活的线程 > 最小线程数
        if (busyNum * 2 < liveNum && liveNum > pool->minNum)
        {
            pthread_mutex_lock(&pool->mutexPool);
            pool->exitNum = NUMBER;
            pthread_mutex_unlock(&pool->mutexPool);
            // 工作线程自杀
            for (int i = 0; i < NUMBER; i++)
            {
                pthread_cond_signal(&pool->notEmpty);
            }
        }
    }
}

template <typename T>
void ThreadPool<T>::threadExit()
{
    pthread_t tid = pthread_self();
    for (int i = 0; i < maxNum; i++)
    {
        if (threadIDs[i] == tid)
        {
            threadIDs[i] = 0;
            cout << "threadExit called, " << to_string(tid) << " exiting " << endl;
            break;
        }
    }
    pthread_exit(NULL);
}

template <typename T>
void ThreadPool<T>::addTask(Task<T> task)
{
    if (shutdown)
    {
        pthread_mutex_unlock(&mutexPool);
        return;
    }
    // 添加任务
    taskQ->addTask(task);
    pthread_cond_signal(&notEmpty);
}

template <typename T>
int ThreadPool<T>::getBusyNum()
{
    pthread_mutex_lock(&mutexPool);
    int busyNum = this->busyNum;
    pthread_mutex_unlock(&mutexPool);
    return busyNum;
}

template <typename T>
int ThreadPool<T>::getAliveNum()
{
    pthread_mutex_lock(&mutexPool);
    int liveNum = this->liveNum;
    pthread_mutex_unlock(&mutexPool);
    return liveNum;
}

template <typename T>
ThreadPool<T>::~ThreadPool()
{
    shutdown = true;
    // 阻塞回收管理者线程
    pthread_join(managerID, NULL);
    // 唤醒阻塞的消费者线程
    for (int i = 0; i < liveNum; i++)
    {
        pthread_cond_signal(&notEmpty);
    }
    if (taskQ)
    {
        delete taskQ;
    }
    if (threadIDs)
    {
        delete[] threadIDs;
    }
    pthread_mutex_destroy(&mutexPool);
    pthread_cond_destroy(&notEmpty);
}
